<template>
  <teleport :to="to">
    <div class="opeaMenu-mark" v-if="showDialog">
      <transition name="fade">
        <div
          class="opeaMenu-dialog"
          v-show="showDialogContent"
          :style="({ '--dialogWid': dialogWid } as any)"
        >
          <div class="opeaMenu-dialog__title">
            <span>{{ title }}</span>
            <SvgIcon icon-class="close" popper-class="title-close" @click="closeDialog" />
          </div>
          <div class="opeaMenu-dialog__main">
            <slot></slot>
          </div>
          <div class="opeaMenu-dialog__footer">
            <template v-if="!oneButton"
              ><el-button
                class="footer-cancel"
                :disabled="isLoading"
                @click="closeDialog"
                >{{ cancelText }}</el-button
              >
              <el-button
                class="footer-confirm"
                type="primary"
                :disabled="isLoading"
                :loading="isLoading"
                @click="emits('confirm')"
                ><template #loading><Loading /></template>{{ confirmText }}</el-button
              ></template
            ><el-button
              v-else
              type="primary"
              style="width: 100%"
              :disabled="isLoading"
              :loading="isLoading"
              @click="emits('confirm')"
              ><template #loading><Loading /></template>{{ confirmText }}</el-button
            >
          </div>
        </div></transition
      >
    </div>
  </teleport>
</template>

<script lang="ts" setup>
import { ref, watch, nextTick, watchEffect } from "vue";

const props = withDefaults(
  defineProps<{
    modelValue: boolean;
    to: string;
    width?: number | string;
    title: string;
    cancelText?: string;
    confirmText?: string;
    // 是否正在操作中(发送请求中)
    isLoading: boolean;
    oneButton?: boolean;
  }>(),
  {
    width: "40%",
    cancelText: "取消",
    confirmText: "确认",
    oneButton: false,
  }
);

const emits = defineEmits<{
  (e: "update:modelValue", show: boolean): void;
  (e: "confirm"): void;
}>();

/**
 * 对话框的宽度
 */
const dialogWid = ref<string>("");

watchEffect(() => {
  if (props.width) {
    if (!isNaN(+props.width)) dialogWid.value = `${props.width}px`;
    else if (
      typeof props.width === "string" &&
      (/^\d+%$/.test(props.width) || /^\d+px$/.test(props.width))
    )
      dialogWid.value = props.width;
  } else dialogWid.value = "40%";
});

/**
 * 是否显示确认操作的对话框
 */
const showDialog = ref<boolean>(false);
/**
 * 是否显示确认操作的对话框的内容
 */
const showDialogContent = ref<boolean>(false);

watch(
  () => props.modelValue,
  (show: boolean) => {
    if (show) {
      showDialog.value = true;
      nextTick(() => (showDialogContent.value = true));
    } else {
      showDialogContent.value = false;
      setTimeout(() => (showDialog.value = false), 200);
    }
  },
  { immediate: true }
);

// 是否关闭对话框
const closeDialog = () => {
  if (!props.isLoading) emits("update:modelValue", false);
};
</script>

<style lang="scss" scoped>
.fade {
  @include fade(0.15s, ease);
}

.opeaMenu {
  &-mark {
    position: absolute;
    inset: 0;
    z-index: 1003;
  }

  &-dialog {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate3d(-50%, -50%, 0);
    background-color: #fff;
    width: var(--dialogWid);
    border-radius: 6px;
    box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.12);
    padding: 3px 0 8px 0;

    &__title {
      position: relative;
      padding: 6px 10px 8px;

      span {
        font-size: 12px;
        color: $dimFontCor;
      }

      .title-close {
        position: absolute;
        right: 3%;
        top: 6px;
        color: #909399;
        cursor: pointer;
        transition: color 0.15s;

        &:hover {
          color: #79bbff;
        }
      }
    }

    &__main {
      padding: 10px 0 15px;
      color: #333;
      font-size: 13px;
      text-align: center;
    }

    &__footer {
      padding: 12px 25px;
      .footer {
        &-cancel {
          width: 35%;
        }

        &-confirm {
          width: 35%;
          margin-left: 30%;
        }
      }
    }
  }
}
</style>
